package demo.android.com.mvpdemo.myRetrofit;

import com.google.gson.Gson;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

import demo.android.com.mvpdemo.myRetrofit.http.GET;
import demo.android.com.mvpdemo.myRetrofit.http.POST;
import demo.android.com.mvpdemo.myRetrofit.http.Query;
import okhttp3.ResponseBody;

/**
 * Created by Vya on 2018/2/2 0002.
 */

public class ServiceMethod {
    final Retrofit retrofit;
    final Method method;
    String httpMethod;
    String relativeUrl;
    final ParameterHandler<?>[] parameterHandlers;
    public ServiceMethod(Builder builder) {
        this.retrofit = builder.retrofit;
        this.method = builder.method;
        this.httpMethod = builder.httpMethod;
        this.relativeUrl = builder.relativeUrl;
        this.parameterHandlers = builder.parameterHandlers;
    }

    public okhttp3.Call createNewCall(Object[] args) {
        //需要一个对象专门用来添加参数
        RequestBuilder requestBuilder = new RequestBuilder(retrofit.baseUrl,relativeUrl,httpMethod,parameterHandlers,args);

        return retrofit.callFactory.newCall(requestBuilder.build());
    }

    public <T> T parseBody(ResponseBody responseBody) {
        //获取解析的类型  T  获取方法返回值的类型
        Type returnType = method.getGenericReturnType();
        Class<T> dataClass = (Class<T>)((ParameterizedType) returnType).getActualTypeArguments()[0];
        //应该使用解析工厂去转换
        Gson gson = new Gson();
        T body = gson.fromJson(responseBody.charStream(),dataClass);
        return body;
    }

    public static class Builder{

        final Retrofit retrofit;
        final Method method;
        final Annotation[] methodAnnotations;
        String httpMethod;
        String relativeUrl;
        Annotation[][] parameterAnnotations;
        final ParameterHandler<?>[] parameterHandlers;
        public Builder(Retrofit retrofit,Method method){ //method是动态代理传入过来的Method
            this.retrofit = retrofit;
            this.method = method;
            methodAnnotations = method.getAnnotations();
            //二维数组

            parameterAnnotations = method.getParameterAnnotations();
            parameterHandlers = new ParameterHandler[parameterAnnotations.length];
        }

        public ServiceMethod build() {
            //解析 Annotation
            for(Annotation methodAnnotation: methodAnnotations){
                //方法解析  POST GET
                parseAnnotationMethod(methodAnnotation);
            }

            //解析参数注解
            int count = parameterHandlers.length;
            for(int i=0;i<count;i++){
                Annotation parameter = parameterAnnotations[i][0];
                //涉及到一个模板和策略两种设计模式
                if(parameter instanceof Query){
                    //一个个封装成ParameterHandler  不同的参数注解选择不同的参数策略
                    parameterHandlers[i] = new ParameterHandler.Query<>(((Query) parameter).value());
                }
            }


            return new ServiceMethod(this);
        }

        private void parseAnnotationMethod(Annotation methodAnnotation) {
            if(methodAnnotation instanceof GET){
                parseMethodAndPath("GET",((GET)methodAnnotation).value());
            }else if(methodAnnotation instanceof POST){
                parseMethodAndPath("POST",((POST)methodAnnotation).value());
            }
        }

        private void parseMethodAndPath(String method, String value) {
            this.httpMethod = method;
            this.relativeUrl = value;
        }
    }
}
